(function (fruit, _, support, global, document, undefined) {
    var eventEngine = fruit.eventEngine;
    var EventHandler = fruit.event.EventHandler;
    var cache = fruit.cache;
    var rsimpleFileds = /^(?:text|password|textarea|file)$/i;

    function getValue(inElement) {
        var type = inElement.type,
            val = inElement.value,
            result;
        switch (type) {
            case "radio":
            case "checkbox":
                result = inElement.name ? inElement.ownerDocument.getElementsByName(inElement.name) : [inElement];
                break;
            case "select-one":
                val = inElement.selectedIndex;
                break;
        }
        if (result) {
            for (var i = 0, ri = 0, re = [], elem; elem = result[i++];) {
                re[ri++] = elem["checked"];
            }
            val = re.join("-");
        }
        return val;
    }

    function initData(inDataString) {
        if (inDataString) {
            var el;
            document.onbeforeactivate = function () {
                if (el = global.event.srcElement) {
                    cache.data(el, inDataString, getValue(el));
                }
            };
        }
    }

    function hasDataChange(inEvent, inDataString) {
        var el, cacheData, currentData;
        if (el = inEvent.srcElement) {
            //undefined or ""
            cacheData = cache.data(el, inDataString) || "";
            currentData = getValue(el) || "";
            if (currentData != cacheData) {
                cache.data(el, inDataString, currentData);
                return true;
            }
        }
        return false;
    }

    var ChangeEventHandler = fruit.define(EventHandler, {
        methods:{
            init:function () {
                this.inherited('change');
                this.__dataString = "__changeEventData__";
            },
            activate:function () {
                if (!this._active) {
                    this._active = true;
                    initData(this.__dataString);
                    eventEngine.addEventListener(document, 'focusout', this._dispatch);
                    eventEngine.addEventListener(document, 'click', this._dispatch);
                    eventEngine.addEventListener(document, 'keyup', this._dispatch);
                }
            },
            deactivate:function () {
                if (this._active) {
                    this._active = false;
                    eventEngine.removeEventListener(document, 'focusout', this._dispatch);
                    eventEngine.removeEventListener(document, 'click', this._dispatch);
                    eventEngine.removeEventListener(document, 'keyup', this._dispatch);
                }
            },
            initPayload:function (payload) {
                this.inherited(payload);
                var event = payload.event;
                var iFormType, type;
                (iFormType = event.srcElement.type) && (iFormType = iFormType.toLowerCase());
                type = event.type;
                payload.ignore = true;
                if ("focusout" == type || !rsimpleFileds.test(iFormType)) {
                    if (hasDataChange(event, this.__dataString)) {
                        payload.ignore = false;
                    }
                }
            }
        }
    });
    var InputEventHandler = fruit.define(EventHandler, {
        methods:{
            init:function () {
                this.inherited('input');
                this.__dataString = "__inputEventData__";
            },
            activate:function () {
                if (!this._active) {
                    this._active = true;
                    initData(this.__dataString);
                    eventEngine.addEventListener(document, 'keyup', this._dispatch);
                    eventEngine.addEventListener(document, 'keypress', this._dispatch);
                }
            },
            deactivate:function () {
                if (this._active) {
                    this._active = false;
                    eventEngine.addEventListener(document, 'keyup', this._dispatch);
                    eventEngine.addEventListener(document, 'keypress', this._dispatch);
                }
            },
            initPayload:function (payload) {
                this.inherited(payload);
                payload.ignore = !hasDataChange(event, this.__dataString);
            }
        }
    });
    var DragEventHandler = fruit.define(EventHandler, {
        statics:{
            target:null
        },
        methods:{
            initTarget:function (payload) {
                this.inherited(payload);
                switch (this._type) {
                    case 'dragstart':
                        DragEventHandler.target = payload.target;
                        break;
                    case 'drag':
                        payload.target = DragEventHandler.target;
                        break;
                    case 'dragend':
                        payload.target = DragEventHandler.target;
                        DragEventHandler.target = null;
                        break;
                }
            }
        }
    });
    if (!support.w3cFocus) {
        eventEngine.registerEventHandler('focus', new EventHandler('focus', 'focusin'));
        eventEngine.registerEventHandler('blur', new EventHandler('blur', 'focusout'));
    }
    if (!support.onmousewheel) {
        eventEngine.registerEventHandler('mousewheel', new EventHandler('mousewheel', 'DOMMouseScroll'));
    }
    if (!support.w3cChange) {
        eventEngine.registerEventHandler('change', new ChangeEventHandler());
    }
    if (!support.w3cInput) {
        eventEngine.registerEventHandler('input', new InputEventHandler());
    }
    eventEngine.registerEventHandler('dragstart', new DragEventHandler('dragstart', 'mousedown'));
    eventEngine.registerEventHandler('drag', new DragEventHandler('drag', 'mousemove'));
    eventEngine.registerEventHandler('dragend', new DragEventHandler('dragend', 'mouseup'));
}(fruit, fruit.util, fruit.support, window, document, undefined));